package com.zackeus.mvvm.api;


import androidx.annotation.NonNull;

import com.zackeus.common.utils.StringUtils;
import com.zackeus.mvvm.api.annotation.API;
import com.zackeus.mvvm.api.cookie.CookieJarImpl;
import com.zackeus.mvvm.api.cookie.store.PersistentCookieStore;
import com.zackeus.mvvm.api.interceptor.TimeoutInterceptor;
import com.zackeus.mvvm.api.interceptor.CacheInterceptor;
import com.zackeus.mvvm.api.interceptor.logging.LoggingInterceptor;
import com.zackeus.common.utils.ObjectUtils;
import com.zackeus.common.utils.Utils;

import java.util.concurrent.TimeUnit;

import okhttp3.ConnectionPool;
import okhttp3.CookieJar;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.internal.platform.Platform;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
*
* @ClassName: ApiServiceManager
* @Description: Retrofit+Rxjava网络层封装
* @Author: zz
* @Date: 2021/1/4 11:24
*/
public class ApiServiceManager {

    private static volatile ApiServiceManager mInstance;

    public static ApiServiceManager getInstance() {
        if (mInstance == null) {
            synchronized (ApiServiceManager.class) {
                if (mInstance == null) {
                    mInstance = new ApiServiceManager();
                }
            }
        }
        return mInstance;
    }

    /**
     * 构建 OkHttpClient 实例
     * @return
     */
    @NonNull
    private OkHttpClient buildClient(@NonNull API api, Interceptor[] interceptors) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();

        /* 连接超时 */
        builder.connectTimeout(api.connectTimeout(), TimeUnit.SECONDS);
        /* 读超时 */
        builder.readTimeout(api.readTimeout(), TimeUnit.SECONDS);
        /* 写超时 */
        builder.writeTimeout(api.writeTimeout(), TimeUnit.SECONDS);

        // SSL支持
        SSLSocketManager.SSLParams sslParams = SSLSocketManager.getSslSocketFactory();
        builder.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager);
        builder.hostnameVerifier(SSLSocketManager.UnSafeHostnameVerifier);

        // cookie 管理
        CookieJar cookieJar =  new CookieJarImpl(new PersistentCookieStore(Utils.getContext()));
        builder.cookieJar(cookieJar);

        /* 缓存选项 */
        if (api.cacheEnable()) {
            builder.addInterceptor(new CacheInterceptor(Utils.getContext()));
        }

        /* 自定义拦截器 */
        builder.addInterceptor(new TimeoutInterceptor());

        /* 拦截器注入 例如 API token 植入 */
        if (ObjectUtils.isNotEmpty(interceptors)) {
            for (Interceptor interceptor : interceptors) {
                builder.addInterceptor(interceptor);
            }
        }

        /* 连接池注入 */
        /* 可根据自己的机型设置同时连接的个数和时间，默认不启用 */
        if (api.maxIdleConnections() > 0) {
            ConnectionPool pool = new ConnectionPool(api.maxIdleConnections(), api.keepAliveDuration(), TimeUnit.SECONDS);;
            builder.connectionPool(pool);
        }

        /* 日志选项 */
        boolean logEnable = api.logEnable();
        if (logEnable && !(api.logDebugOnly() && Utils.isApkInDebug())) {
            logEnable = Boolean.FALSE;
        }

        builder.addInterceptor(new LoggingInterceptor
                .Builder()                                      // 构建者模式
                .loggable(logEnable)                            // 设置日志的启用
                .setLevel(api.logLevel())                       // 打印的等级
                .log(Platform.INFO)                             // 打印类型
                .request("Request")                             // request的Tag
                .response("Response")                           // Response的Tag
                .addHeader("log-header", "I am the log request header.") // 添加打印头, 注意 key 和 value 都不能是中文
                .build());
        return builder.build();
    }

    /**
     * 构建 API Service
     * @param service api 接口类
     * @param <T>
     * @return
     */
    @NonNull
    public <T> T create(@NonNull final Class<T> service) {
        return this.create(service, null);
    }

    /**
     * 构建 API Service
     * @param service
     * @param interceptors api 接口类
     * @param <T>
     * @return
     */
    public <T> T create(@NonNull final Class<T> service, Interceptor[] interceptors) {
        API api = service.getAnnotation(API.class);

        if (ObjectUtils.isNull(api)) {
            throw new IllegalStateException("The api service must add API annotation.");
        }
        if (StringUtils.isBlank(api.baseURL())) {
            throw new IllegalStateException("baseUrl can not be null");
        }

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(api.baseURL())
                .client(buildClient(api, interceptors))
                .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        return retrofit.create(service);
    }
}
